<template>
	<!-- #ifdef MP-WEIXIN -->
	<picker mode="multiSelector" :range="addressRange" range-key="name" @change="pickerChange"
		@columnchange="columnchange" :value="pickerValue" @cancel="$emit('cancel')" :disabled="disabled">
		<slot v-if="$slots.default"></slot>
		<input v-else type="text" :value="inputStr" disabled placeholder="点击选择">
	</picker>
	<!-- #endif -->

	<!-- #ifdef H5 -->
	<uni-data-picker ref="picker" v-model="h5Value" :localdata="h5AddressData" popup-title="请选择地址" @change="onH5Change">
		<template v-slot:default="{ text }">
			<input type="text" :value="inputStr || text" readonly inputmode="none" placeholder="点击选择地址" @click.stop="handleOpenPicker"
				style="caret-color: transparent;">
		</template>
	</uni-data-picker>
	<!-- #endif -->
</template>

<script>
	import address from "./address.json"; // 可注释 注释此行请删除utils目录下的address.json文件
	export default {
		/**
		 * @param modelValue Array(string) ['四川省', '成都市', '武侯区']
		 * @param codeValue Array(string | number) [ "51","5101", "510107" ]
		 * @param selectIndex Array(number) [ 0, 0, 0 ]
		 * @param disabled 禁用
		 * @param loadJson 自定义加载地址json
		 */
		props: {
			modelValue: Array,
			value: Array,
			codeValue: Array,
			disabled: {
				type: Boolean,
				default: false,
			},
			selectIndex: {
				type: Array,
				default: () => [0, 0, 0],
			},
			loadJson: {
				type: Function,
			}
		},
		model: {
			prop: 'value',
			event: 'input'
		},
		emits: [
			"update:modelValue",
			"update:codeValue",
			"columnchange",
			"change",
			"cancel",
			"input",
		],
		computed: {
			inputStr() {
				const value = this._value || [];
				if (value.length >= 3) {
					return value.filter(v => v && v !== '请选择').join('');
				}
				if (this.h5Value?.length >= 3) {
					return this.h5Value.map(item => item?.text).join('');
				}
				return '';
			},
			_value() {
				return this.value || this.modelValue || [];
			}
		},

		watch: {
			h5Value(newVal) {
				// #ifdef H5
				if (newVal?.length >= 3) {
					this.$emit("input", newVal.map(item => item?.text));
					this.$emit("update:modelValue", newVal.map(item => item?.text));
				}
				// #endif
			},
			_value() {
				this.setDefByName();
			},
			codeValue() {
				this.setDefByCode();
			},
		},
		data() {
			return {
				addressRange: [],
				pickerValue: [0, 0, 0],
				pleaseSelect: {
					name: '请选择',
					code: '',
					child: []
				},
				h5Value: [],
				h5AddressData: []
			};
		},
		async created() {
			// #ifdef H5
			this.$nextTick(() => {
				setTimeout(() => {
					this.h5AddressData = this.formatAddressForH5(address);
				}, 100);
			});
			// #endif
			this.pickerValue = [...this.selectIndex];
			let initialData = [];
			if (this.loadJson) {
				const addressJson = await this.loadJson();
				if (!Array.isArray(addressJson)) {
					throw new Error('loadJson 必须返回数组');
				}
				initialData = addressJson;
				console.warn('<sh-address> 您已自定义地址json, 请删除插件源码中指定可删除代码, 以减小应用体积');
			} else {
				initialData = address;
			}
			this.addressRange[0] = [this.pleaseSelect, ...initialData];
			this.addressRange[1] = [this.pleaseSelect];
			this.addressRange[2] = [this.pleaseSelect];

			this.setDefByCode();
			this.setDefByName();
		},
		methods: {
			handleOpenPicker() {
				// #ifdef H5
				this.$refs.picker.show();
				// #endif
			},
			formatAddressForH5(data) {
				return data.map(province => ({
					text: province.name,
					value: province.code,
					children: province.child.map(city => ({
						text: city.name,
						value: city.code,
						children: city.child.map(area => ({
							text: area.name,
							value: area.code,
						})),
					})),
				}));
			},
			onH5Change(e) {
				try {
					const values = e.detail.value;
					if (!values || values.length < 3) return;

					const [province, city, area] = values;
					const result = {
						province: province?.text,
						city: city?.text,
						area: area?.text,
						provinceCode: province?.value,
						cityCode: city?.value,
						areaCode: area?.value,
					};
					this.$emit("input", [result.province, result.city, result.area].filter(Boolean));
					this.$emit("update:modelValue", [result.province, result.city, result.area].filter(Boolean));
					this.$emit("change", result);
				} catch (err) {
					console.error('地址选择异常:', err);
				}
			},
			columnchange(e) {
				const {
					column,
					value
				} = e.detail;
				this.$emit("columnchange", e.detail);

				if (column === 0) {
					if (value === 0) { // 选择了"请选择"
						this.addressRange[1] = [this.pleaseSelect];
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue = [0, 0, 0];
					} else {
						this.addressRange[1] = [this.pleaseSelect, ...this.addressRange[0][value].child];
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue[1] = 0;
						this.pickerValue[2] = 0;
					}
				}

				if (column === 1) {
					if (value === 0) { // 选择了"请选择"
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue[2] = 0;
					} else {
						this.addressRange[2] = [this.pleaseSelect, ...this.addressRange[1][value].child];
						this.pickerValue[2] = 0;
					}
				}

				this.$forceUpdate()
			},
			pickerChange(e) {
				const v = e.detail.value;
				let province = '',
					city = '',
					area = '';
				let provinceCode = '',
					cityCode = '',
					areaCode = '';

				// 处理省级选择
				if (v[0] !== 0) {
					const provinceData = this.addressRange[0][v[0]];
					province = provinceData.name;
					provinceCode = provinceData.code;

					// 处理市级选择
					if (v[1] !== 0) {
						const cityData = this.addressRange[1][v[1]];
						city = cityData.name;
						cityCode = cityData.code;

						// 处理区级选择
						if (v[2] !== 0) {
							const areaData = this.addressRange[2][v[2]];
							area = areaData.name;
							areaCode = areaData.code;
						}
					}
				}

				this.$emit("change", {
					areaCode,
					area,
					cityCode,
					provinceCode,
					province,
					city,
				});

				const result = [province, city, area].filter(v => v !== '请选择' && v !== '');
				this.$emit("input", result);
				this.$emit("update:modelValue", result);
				this.$emit("update:codeValue", [provinceCode, cityCode, areaCode].filter(Boolean));
			},
			setDefByCode() {
				if (this.codeValue instanceof Array && this.codeValue.length >= 1) {
					const provinceIndex = this.addressRange[0].findIndex(
						(item, index) => index > 0 && item.code === this.codeValue[0]?.toString()
					);

					if (provinceIndex === -1) {
						this.addressRange[1] = [this.pleaseSelect];
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue = [0, 0, 0];
						return;
					}

					this.addressRange[1] = [this.pleaseSelect, ...this.addressRange[0][provinceIndex].child];

					const cityIndex = this.addressRange[1].findIndex(
						(item, index) => index > 0 && item.code === this.codeValue[1]?.toString()
					);

					if (cityIndex === -1) {
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue = [provinceIndex, 0, 0];
						return;
					}

					this.addressRange[2] = [this.pleaseSelect, ...this.addressRange[1][cityIndex].child];

					const areaIndex = this.addressRange[2].findIndex(
						(item, index) => index > 0 && item.code === this.codeValue[2]?.toString()
					);

					this.pickerValue = [provinceIndex, cityIndex, areaIndex === -1 ? 0 : areaIndex];
				} else {
					this.addressRange[1] = [this.pleaseSelect];
					this.addressRange[2] = [this.pleaseSelect];
					this.pickerValue = [0, 0, 0];
				}
			},
			setDefByName() {
				if (this._value instanceof Array && this._value.length >= 1) {
					const provinceIndex = this.addressRange[0].findIndex(
						(item, index) => index > 0 && item.name === this._value[0]
					);

					if (provinceIndex === -1) {
						this.addressRange[1] = [this.pleaseSelect];
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue = [0, 0, 0];
						return;
					}

					this.addressRange[1] = [this.pleaseSelect, ...this.addressRange[0][provinceIndex].child];

					const cityIndex = this.addressRange[1].findIndex(
						(item, index) => index > 0 && item.name === this._value[1]
					);

					if (cityIndex === -1) {
						this.addressRange[2] = [this.pleaseSelect];
						this.pickerValue = [provinceIndex, 0, 0];
						return;
					}

					this.addressRange[2] = [this.pleaseSelect, ...this.addressRange[1][cityIndex].child];

					const areaIndex = this.addressRange[2].findIndex(
						(item, index) => index > 0 && item.name === this._value[2]
					);

					this.pickerValue = [provinceIndex, cityIndex, areaIndex === -1 ? 0 : areaIndex];
				} else {
					this.addressRange[1] = [this.pleaseSelect];
					this.addressRange[2] = [this.pleaseSelect];
					this.pickerValue = [0, 0, 0];
				}
			},
		},
	};
</script>